home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
LIBIP
/
Descript.c.old
< prev
next >
Wrap
Text File
|
1999-09-11
|
9KB
|
364 lines
/*
** descript.c
**
** Practical Algorithms for Image Analysis
**
** Copyright (c) 1997 ????
*/
/*
** DESCRIPT
**
** evaluation of Fourier descriptors for a plane curve
** encoded in a set {delta_phi(k), l(k)};
**
** references:
** C. T. Zahn,
** Proc. Joint Intern. Conf. on Artif. Intelligence, May 1969, pp. 621 - 628;
** SLAC Report 70, Stanford Linear Accelerator Center, 1968;
** C. T. Zahn & R. Z. Roskies, IEEE Trans. Comp., Vol C-21, 269 - 281 (1972);
**
** -->the truncated Fourier expansion derived by Z & R is computed
** in form of inner products using array processor functions
**
** -->test shapes (see Z & R):
** four (xdrawfour.c), inverted L (fdzahnl.c)
**
** ---------------------------------------------------------------------------
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "ip.h"
#define EPS 0.00000001
#define SQ2 1.414213562
#define ON 1
#define OFF 0
#define FD_DEBUG ON
/*
* descriptors()
* DESCRIPTION:
* evaluate ZAHN-ROSKIES Fourier descriptors
* ARGUMENTS:
* dphik: delta phik for polygon (float *)
* dlk: delta lk for polygon (float *)
* mcp: length of dphik and dlk (long)
* a_n: Fourier coefficients array (float *)
* b_n: Fourier coefficients array (float *)
* n_order: order of Fourier descriptors to compute (long)
* RETURN VALUE:
* none
*/
void
descriptors (float *dphik, float *dlk, long mcp, float *a_n, float *b_n, long n_order)
{
int k, n_ord;
int fund_flag = OFF;
float real_length, length;
float dc_term, a, b, part_sum;
float sne1k, snen, csn1k, csnn;
float *angle;
float *sne1, *sne, *csn1, *csn;
float *mod, *arg;
/*
** compute (in place) running sums of the elements in dlk
** and the corresponding phase angles required in the evaluation
** of the fundamental
*/
angle = (float *)calloc((int)mcp, sizeof(float));
sne1 = (float *)calloc((int)mcp, sizeof(float));
csn1 = (float *)calloc((int)mcp, sizeof(float));
sne = (float *)calloc((int)mcp, sizeof(float));
csn = (float *)calloc((int)mcp, sizeof(float));
if((angle == NULL) || (sne == NULL) || (csn1 == NULL) || (sne == NULL)
|| (csn == NULL))
{
printf("memory allocation error in function descriptors\n");
exit(1);
}
/*
** evaluate contour length, based on curvature points
*/
part_sum = *(dlk+0);
for(k=1; k<mcp; k++)
{
part_sum += *(dlk+k);
*(dlk+k) = part_sum; /* array of partial sums */
}
length = *(dlk+mcp-1);
for(k=0; k<mcp; k++)
*(angle+k) = (float)(2*PI*(*(dlk+k))/length);
real_length = (float)(0.5*length);
printf("\n...length = %f\n", real_length);
/*
** dphik contains elements of delta_phik multiplied by PI/4;
** to speed up computation, factor out PI
*/
for(k=0; k<mcp; k++)
*(dphik+k) *= (float)0.25;
#ifdef FD_DEBUG
printf("...elements of dphik and dlk:\n");
for(k=0; k<mcp; k++)
printf("%7.4f %7.4f\n", *(dphik+k), *(dlk+k) );
#endif
/*
* compute DC term
*/
vdot(dphik, dlk, &dc_term, mcp);
dc_term = (float)(-PI*(1.0 + dc_term/length));
printf("...and we have a result for the DC term: %f \n", dc_term);
/*
** execute routine to compute sine and
** cosine terms for fundamental, then fetch results
*/
for(n_ord=0; n_ord<(int)n_order; n_ord++)
{
/*
* compute coefficients for fundamental;
*/
if(n_ord == 0)
{
for(k = 0; k < mcp; k++)
*(angle + k) = *(angle + k) * (n_ord + 1);
vsin(angle, sne1, mcp);
vcos(angle, csn1, mcp);
for (k=0; k<mcp; k++)
{
csn1k = *(csn1+k);
sne1k = *(sne1+k);
if( fabs(csn1k) < EPS ) csn1k = (float)0.0;
if( fabs(sne1k) < EPS ) sne1k = (float)0.0;
*(sne+k) = *(sne1+k) = sne1k;
*(csn+k) = *(csn1+k) = csn1k;
}
fund_flag = ON;
}
/*
** employ double angle formulas to compute higher order coefficients
*/
else
{
if( fund_flag != ON )
{
printf("\n");
printf("hey, evaluate fundamental first!\n");
printf(" something wrong!!\n");
exit(1);
}
for (k=0; k<mcp; k++)
{
snen = *(sne+k);
csnn = *(csn+k);
*(sne+k) = snen*(*(csn1+k))+csnn*(*(sne1+k));
*(csn+k) = csnn*(*(csn1+k))-snen*(*(sne1+k));
}
#ifdef FD_DEBUG
printf("\n...n_ord = %d:\n", n_ord);
for(k=0; k<10; k++)
printf("......sne[%d] = %f csn[%d] = %f\n",
k, *(sne+k), k, *(csn+k) );
#endif
}
/*
** compute coefficients a_n, b_n
*/
vdot(dphik, sne, &a, mcp);
vdot(dphik, csn, &b, mcp);
*(a_n+n_ord) = -a/(float)(n_ord+1);
*(b_n+n_ord) = b/(float)(n_ord+1);
}
printf("...descriptors up to %ld-th order are:\n", n_order);
for(n_ord=0; n_ord<(int)n_order; n_ord++)
printf ("%7.3f %7.3f\n", *(a_n+n_ord), *(b_n+n_ord));
mod = (float *)calloc((int)n_order, sizeof(float));
arg = (float *)calloc((int)n_order, sizeof(float));
/*
** calculate xy to polar coordinate transformation
*/
vrtop(a_n, b_n, mod, arg, n_order);
printf("...polar descriptors up to %ld-th order are:\n", n_order);
for(n_ord=0; n_ord<(int)n_order; n_ord++)
{
if( *(arg+n_ord) < 0.0) *(arg+n_ord) += (float)(2.0*PI);
printf("%7.3f %7.3f\n", *(mod+n_ord), *(arg+n_ord));
}
free(angle);
free(sne1);
free(csn1);
free(sne);
free(csn);
}
/*
* vdot()
* DESCRIPTION:
* take the dot product of 2 vectors
* and compute the sum
* ARGUMENTS:
* v1: first vector (float *)
* v2: second vector (float *)
* vsum: vector sum (float *)
* vlen: length of vectors (long)
* RETURN VALUE:
* none
*/
void
vdot(float *v1, float *v2, float *vsum, long vlen)
{
float rsum = (float)0.0;
int i;
for(i = 0; i < vlen; i++)
rsum = rsum + *(v1 + i) * (*(v2 + i));
*vsum = rsum;
}
/*
* vcos()
* DESCRIPTION:
* takes the cosine of a vector
* ARGUMENTS:
* source: input vector (float *) NOTE: radians!!
* dest: output vector (float *)
* vlen: vector length (long)
* RETURN VALUE:
* none
*/
void
vcos(float *source, float *dest, long vlen)
{
int i;
for(i = 0; i < vlen; i++)
*(dest + i) = (float)cos((double)*(source + i));
}
/*
* vsin()
* DESCRIPTION:
* takes the sine of a vector
* ARGUMENTS:
* source: input vector (float *) NOTE: radians!!
* dest: output vector (float *)
* vlen: vector length (long)
* RETURN VALUE:
* none
*/
void
vsin(float *source, float *dest, long vlen)
{
int i;
for(i = 0; i < vlen; i++)
*(dest + i) = (float)sin((double)*(source + i));
}
/*
* vrtop()
* DESCRIPTION:
* converts rectangular cartesian
* coordinates to polar
* ARGUMENTS:
* x: input x vector (float *)
* y: input y vector (float *)
* mod: modulus output vector (float *)
* arg: atan2 output vector (float *)
* vlen: vector lengths (long)
* RETURN VALUE:
* none
*/
void
vrtop(float *x, float *y, float *mod, float *arg, long vlen)
{
int i;
for(i = 0; i < vlen; i++) {
*(mod + i) = (*(x + i))*(*(x + i)) + (*(y + i))*(*(y + i));
*(arg + i) = (float)atan2(*(y + i), *(x + i));
}
}
/*
* msdescriptors()
* DESCRIPTION:
* wrapper for call to descriptors()
* ARGUMENTS:
* delta_phik: delta phik for polygon (float *)
* delta_lk: delta lk for polygon (float *)
* mcp: length of dphik and dlk (long)
* a_n: Fourier coefficients array (float *)
* b_n: Fourier coefficients array (float *)
* n_order: order of Fourier descriptors to compute (long)
* RETURN VALUE:
* none
*/
void
msdescriptors(float *delta_phik, float *delta_lk, long mcp, float *a_n, float *b_n, long n_order)
{
int k;
#ifdef FD_DEBUG
printf("\nevaluation of Fourier descriptors (Zahn & Roskies)\n");
printf("--------------------------------------------------\n");
printf("...given: two vectors, delta_phik[] and delta_lk[]\n");
printf(" delta_phik:\n");
for(k=0; k<(int)mcp; k++)
{
printf( "%7.2f ",*(delta_phik+k) );
if( (k+1)%8 == 0)
printf ("\n");
}
printf ("\n delta_lk:\n");
for (k=0; k<(int)mcp; k++)
{
printf( "%7.2f ",*(delta_lk+k) );
if( (k+1)%8 == 0)
printf ("\n");
}
#endif
if(n_order > mcp)
{
printf("...polygon only has %ld vertices;");
printf(" cannot yield %ld harmonics!\n", mcp, n_order);
exit(1);
}
descriptors(delta_phik, delta_lk, mcp, a_n, b_n, n_order);
}